<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div class="box">
    <span>1</span>
    <span>2</span>
    <span>3</span>
  </div>
  <script>
    // 将两类对象转化为真正的数组 （array-like） (可遍历的对象 set map)
    let array1 = {
      0: 'a',
      1: 'c',
      2: 'b',
      length: 3
    } // 注意，key必须是索引(数字或者字符串都可以)，不然无法转化为数组
    let arr = [].slice.call(array1)
    console.log(arr, 'arr');
    let arr2 = Array.from(array1)
    console.log(arr2, 'arr2');

    // NodeLit对象，将NodeLit对象转化为数组
    let nodeList = document.querySelectorAll('.box span')
    let arr3 = Array.prototype.slice.call(nodeList)
    let arr4 = Array.from(nodeList)
    console.log(arr3, 'arr3');
    console.log(arr4, 'arr4');

    // map
    let map = new Map()
    map.set('key1', '1')
    map.set('key2', '2')
    console.log(map, 'map');
    console.log(Array.from(map), 'map'); // [[key1, 1], [key2, 2]]

    // set
    let set = new Set()
    set.add('1')
    set.add('2')
    console.log(set, 'set');
    console.log(Array.from(set), 'set'); // [1, 2]

    // arguments
    function fn() {
      console.log(arguments, 'arguments');
      console.log(Array.from(arguments), 'arguments'); // [1, 2, 3]
    }
    fn(1,2,3)

    // 字符串
    console.log(Array.from('str'), 'str'); // ['s', 't', 'r']

    // 真数组
    let arr5 = ['1', '2', '3']
    console.log(Array.from(arr5), 'arr5'); // 会返回一个一模一样的数组

    // 扩展运算符无法转化类似数组的对象
    let array2 = {
      0: 'a',
      1: 'c',
      2: 'b',
      length: 3
    }
    // console.log(...array2, 'array2'); // 会报错


    // 返回数组值是3个 [undefined, undefined, undefined]
    console.log(Array.from({length: 3}), 'Array.from({length: 3})');
    // 还没有部署该方法的浏览器，可以使用Array.prototype.slice()方法替代
    const toArray = (() => 
      Array.from ? Array.from : obj => Array.prototype.slice(obj)
    )()
    let aa = {length:3, 0:'first', 1:'second', 2: 'third'}
    console.log(Array.prototype.slice.call(aa, 2)); // 是把['first', 'second', 'third'].slice(2)


    // Array.from方法接受用第二个参数，用来对每个元素进行处理，然后放入数组
    let bb = {length:3, 0: 1, 1: 2, 2: 3}
    console.log(Array.from(bb, x => x * 2), 'Array.from'); // [2, 4, 6]
    // 等同于
    console.log(Array.from(bb).map(x => x * 2), 'Array.from'); // [2, 4, 6]


    // 取出dom节点的文本内容
    let spans = document.querySelectorAll('.box span')
    console.log(Array.from(spans, span => span.textContent)); // 1 2 3

    // 将数组中布尔值为false的转为0
    let cc = [1, , 2, , 3]
    console.log(Array.from(cc, n => n || 0)); // [1,0,2,0,3]

    // 返回各种数据类型
    function typesOf() {
      return Array.from(arguments, arg => typeof arg)
    }
    console.log(typesOf(null, [], {}, 1, '2'));

    // 指定方法运行的参数
    console.log(Array.from({length: 2}, () => 'jack'), "Array.from({length: 2}, () => 'jack')"); // ['jack', 'jack']

    // 另一个作用,将字符串转化为数组，正确的计算字符串的长度
    console.log(Array.from('1你好').length); // 3
    console.log('1你好'.length);
  </script>
</body>
</html>